"""
 Linux用户管理类
• 基类：实现往linux系统里添加用户
• 子类A：
• 能够查看、修改uid和gid、shell等信息
• 子类B：
• 1.能删除用户
• 2.能删除组
• 子类C(A,B)：
• 1.可以单独新建组
• 2.可以将某个用户的gid修改为新建的组的gid
• 3.加入异常机制，异常的名字需要自己定义
"""
import subprocess
import os
# subprocess模块允许你去创建一个新的进程让其执行另外的程序，并与它进行通信，
# 获取标准的输入、标准输出、标准错误以及返回码等。(使用这个模块之前先导入import subprocess)

class Base():
    def add_user(self,name,passwd):
        process = subprocess.Popen(f'useradd {name} -p {passwd}&>/dev/null && \
        echo "{name}创建成功" || echo "{name}创建失败"',shell=True)
        """
        subprocess.Popen()：
        在一些复杂场景中，我们需要将一个进程的执行输出作为另一个进程的输入。在另一些场景中，我们需要先进入到某个输入环境，然后再执行一系列的指令等。
        这个时候我们就需要使用到suprocess的Popen()方法。该方法有以下参数：
        args：shell命令，可以是字符串，或者序列类型，如list,tuple。
        bufsize：缓冲区大小，可不用关心
        stdin,stdout,stderr：分别表示程序的标准输入，标准输出及标准错误
        shell：与上面方法中用法相同
        cwd：用于设置子进程的当前目录
        env：用于指定子进程的环境变量。如果env=None，则默认从父进程继承环境变量
        universal_newlines：不同系统的的换行符不同，当该参数设定为true时，则表示使用\n作为换行符
        """
class A(Base):
    def view_user(self,name):
        process = subprocess.Popen(f'cut -d ":" -f 1,3,4,7 /etc/passwd|grep -E {name}:',shell=True)
        # cut命令截取/etc/passwd里面第1，3，4，7段由“：”分隔开的字符
    def change_user(self,name,uid,gid,shell):
        process = subprocess.Popen(f'usermod -u {uid} -g {gid} -s {shell} {name}&>/dev/null && echo "相关信息已修改成功" ||echo "修改失败"',shell=True)

class B(Base):
    def del_user(self,name):
        process = subprocess.Popen(f'userdel -r {name}&>/dev/null && \
                echo "{name}删除成功" || echo "{name}删除失败"')
    def del_group(self,name):
        process = subprocess.Popen(f'groupdel {name}&>/dev/null && \
                echo "{name}删除成功" || echo "{name}删除失败"')

class C(A,B):
    group = []
    def create_group(self,name,gid):
        process = subprocess.Popen(f'groupadd -g {gid} {name}&>/dev/null && \
        echo "{gid}创建成功" || echo "{gid}创建失败"',shell=True)
        C.group.append(gid)
    def change_gid(self,name,gid):
        if gid in C.group:
            process = subprocess.Popen(f'usermod -g {gid} {name}&>/dev/null && \
            echo "{name}的组信息修改成功" || echo "修改失败"',shell=True)
        else:
            print(f"{gid}不存在")
class Name_error(Exception):
    def __str__(self):
        return "NameError"

while True:
    print('''
    *********Linux 操作手册*********
         （请仔细查看并认真操作）
     添加用户     -->      请输入“1”
     查看用户信息  -->      请输入“2”
     修改用户信息  -->      请输入“3”
     删除用户      -->     请输入“4”
     删除组       -->      请输入“5”
     新建组        -->     请输入“6”
     修改用户组信息  -->     请输入“7”
     退出系统       -->     请输入“0”
    ''')
    operation = input("请输入您需要进行的操作：\n")
    if operation.isdigit():
        if 1 <= int(operation) <= 7:
            if operation == "1":
                a = Base()
                name, passwd = input("请输入您需要创建的用户名和密码，并用空格隔开\n").split()
                if name == "root":
                    raise Name_error
                else:
                    a.add_user(name,passwd)
            elif operation == "2":
                a = A()
                name = input("请输入你需要查看用户信息的用户名：\n")
                a.view_user(name)
            elif operation == "3":
                a = A()
                name,uid,gid,shell = input("请输入您需要修改的用户的用户名、uid,gid以及shell，并用空格隔开\n").split()
                a.change_user(name,uid,gid,shell)
            elif operation == "4":
                a = B()
                name = input("请输入您需要删除的用户名:\n")
                a.del_user(name)
            elif operation == "5":
                a = B()
                name = input("请输入您需要删除的组名：\n")
                a.del_group(name)
            elif operation == "6":
                a = C()
                name,gid = input("请输入创建的组名、指定的gid，并用空格隔开\n").split()
                a.create_group(name,gid)
            elif operation == "7":
                a = C()
                name,gid = input("请输入修改的组名、指定的gid，并用空格隔开\n").split()
                a.change_gid(name,gid)
            elif operation == "0":
                print("您已退出Linux系统。")
                exit()
        else:
            print("如需操作请输入1-7的数字，退出请输入exit")
    else:
        print("输入有误，请重新输入！")


